package com.jasonchoi.security.commons.utils;

import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Date;
import java.util.Objects;

/**
 * @Author: JasonChoi
 * @Date: 2020/1/8 16:26
 */
@Component
public class JwtUtil {

    private static String secretKey;

    private static long expireTime;

    private JwtUtil() {
    }

    public static String generateJwt(JwtInfo info) {
        return Jwts.builder()
                   .setSubject(JSONObject.toJSONString(info))
                   .setExpiration(new Date(System.currentTimeMillis() + expireTime * 60 * 1000))
                   .signWith(SignatureAlgorithm.HS512, secretKey)
                   .compact();
    }

    public static Boolean validJwt(String jwt){
        return Objects.nonNull(getJwtInfo(jwt));
    }

    private static JwtInfo getJwtInfo(String jwt) {
        try {
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt);
            Claims body = claimsJws.getBody();
            return JSONObject.parseObject(body.getSubject(), JwtInfo.class);
        } catch (Exception e) {
            return null;
        }
    }

    public static String getUsername(String jwt) {
        JwtInfo jwtInfo = getJwtInfo(jwt);
        return Objects.isNull(jwtInfo) ? null : jwtInfo.getUsername();
    }

    public static String getUserRole(String jwt) {
        JwtInfo jwtInfo = getJwtInfo(jwt);
        return Objects.isNull(jwtInfo) ? null : jwtInfo.getRole();
    }

    @Data
    @Accessors(chain = true)
    public static class JwtInfo implements Serializable {
        private String username;
        private String role;
    }

    @Value("${global.jwt.secretKey}")
    public void setSecretKey(String secretKey) {
        JwtUtil.secretKey = secretKey;
    }

    @Value("${global.jwt.expireTime}")
    public void setExpireTime(long expireTime) {
        JwtUtil.expireTime = expireTime;
    }
}
